package com.spring.future.common.utils;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Set;

/**
 * Created by liuj on 2016-11-01.
 */
public class ObjectMapperUtils {
    private static Logger logger = LoggerFactory.getLogger(ObjectMapperUtils.class);

    private static ObjectMapper objectMapper = getObjectMapper();

    public static ObjectMapper getObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        objectMapper.registerModule(javaTimeModule);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) ;
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        return objectMapper;
    }

    public static String writeValueAsString(Object object) {
        return writeValueAsString(objectMapper,object);
    }

    public static String writeValueAsString(ObjectMapper objectMapper, Object object) {
        String result = null;
        try {
            result = objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            logger.error(e.getMessage());
        }
        return result;
    }

    public static  <T> T readValue(String json, Class<T> clazz) {
        return readValue(objectMapper, json, clazz);
    }

    public static  <T> T readValue(ObjectMapper objectMapper, String json, Class<T> clazz) {
        T t = null;
        try {
            t = objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return t;
    }


    public static void filterOutAllExcept(ObjectMapper objectMapper, Class clazz, String... propertyArray) {
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept(propertyArray));
        objectMapper.setFilterProvider(filterProvider);
        objectMapper.addMixIn(clazz,MyFilterMixIn.class);
    }

    public static void filterOutAllExcept(ObjectMapper objectMapper, Class clazz, Set<String> properties) {
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept(properties));
        objectMapper.setFilterProvider(filterProvider);
        objectMapper.addMixIn(clazz,MyFilterMixIn.class);
    }

    public static void serializeAllExcept(ObjectMapper objectMapper, Class clazz, String... propertyArray) {
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.serializeAllExcept(propertyArray));
        objectMapper.setFilterProvider(filterProvider);
        objectMapper.addMixIn(clazz,MyFilterMixIn.class);
    }

    public static void serializeAllExcept(ObjectMapper objectMapper, Class clazz, Set<String> properties) {
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.serializeAllExcept(properties));
        objectMapper.setFilterProvider(filterProvider);
        objectMapper.addMixIn(clazz,MyFilterMixIn.class);
    }


    @JsonFilter("myFilter")
    private interface MyFilterMixIn{
    }
}
